<?php

namespace common\base;

/**
 * Description of Rsa
 *
 * @author emhome
 */
class Rsa {

//Block size for encryption block cipher
    private $ENCRYPT_BLOCK_SIZE = 200; // this for 2048 bit key for example, leaving some room
    //Block size for decryption block cipher
    private $DECRYPT_BLOCK_SIZE = 256; // this again for 2048 bit key
    private static $PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAvJ+/tbwkFm8rmTfQ2/w/eEUiFpvRO7KWUVZFkyxon1ML2Nxe
DSgbaxIdE9mDzaPepwvmW1xYwXZvJN7Pq87CJ3uBNlwm0l78Vo+bOT5IMNx4BZSn
J2YXJxidZnFfzfWx+U3MHfYot2pKwyc260kSpouFeEhXX/tjby8O7IfGBmi1+OlE
zRoQ0Eoy5pZPKt7NrOn4v0Vh2vOTEgMuExrhFtjvTgh7TpWRt5s5aLFc5QVMUk+w
SyA9KEaxvgCMeAuINy9rHYsHB5e9HljVUWGsed9f0rESNNTcOTuEen/eUWBb6MHt
TYVWEXMWZLgd3eruVt2VhIz4cfGI/3/ThUo/ZwIDAQABAoIBAQCaiRLq1NqIGsqQ
fB88rBxf79vuw/gXPchTmSflXQPWTJavNFRF2S8leLCj+5g1mWUoXOJ8xVreHacP
gRCJhRqieFgzbipMPo/kZ0FYE8PXbDlU8SZFbCnZ2RvTu10vg3UteGSbw3o2Uvov
iug+uh5ynmpaUoJrW61qgRZsCQzfX/AKbSydv8ChWuvIPg/N3jBeorzn33ypwIWc
2HRy4N9eof0AhBo/CsoHgI+dTuoAqRbXe1XKsbFZBp4+r3vzYNobnXe+MbPry2pV
VRg4vfMl0+r1p3+sbXjqqrw8EWWb+MDmyNG38Dxh7WFKsFwK6eWrQk30A71ZS1Dk
m3hSU+apAoGBAOYjG13I9BCj5AuE/w6+sD94ytY/qK3W4XVxm12TXfz1YfTuZBQZ
ZcBlJYbz5eyMBIq3APSx3KirfzNcYNUzfaJo1TBuNPjUkrrnGD1TQjc9y/fCEtga
VNiysuF6y9g7+4LJTaOHA5mxlB41naUsARjNvPW4QLww8RKuQvLLi/GVAoGBANHS
VklVl06HGFxpxyikEhI8U5oyd2u79Ml2egzQvy7r6RzLiIbVCwE5KKN7Jc/Zg9r5
QdMvYdFImGjvIoc8tk2IehdPIN/Vmf5kqf01xvK68DiG2VUYOthQWUwXalywk3pw
vhs6Y7dIGrlOKHYr5ij8jWgJWzbWZPQEaDB1j+YLAoGAUSJ1ZnYPXcJ6Bnmn9knS
Fz59vFULIeaM6/vWe4IV87WLCG/3RoLBtbezKEXafK/Mdh8Yriv6kFiN6syZsvCJ
TXXKG13vPP6skEoi6JPu10zpGPsJ67g0y4UMvaOuNBjJjg1sWsehxFCv2Iqsfmvq
IxV9ld+UqwRSKXTYU4LhXpUCgYASsNf65GL8HdCvusSA/EyXz0PrQn+c2zttDt7E
cXv2ZBF5/S+GQ0gdrcfO+FNf9pJmWTnh5CCkkgDxqAu9XE0pDvVBSk01Y0O6g6EY
60dzq+9mOaz2hZgIWO/7dUKGSzx39b8ZkdP8KbInu6yjCjoQgJ7gG6VCd0q66gGV
/4L4DQKBgBz9WIcTyk9+PWlXvFYdlmHkZM33kibeoqqAPOnL2CEjSDDp6AYXWqg8
Qe2NAYhFcVxiJwFvjPYY9pjD3Moy0BTcGj5mHhGErub9Aua2OmijGlKuVehivPXK
vNDs8B8r+e6da3W08vqtZHSYhG5+nJqK5HBdZ6E5Cv97uYq5qf/p
-----END RSA PRIVATE KEY-----
";
    private static $PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvJ+/tbwkFm8rmTfQ2/w/
eEUiFpvRO7KWUVZFkyxon1ML2NxeDSgbaxIdE9mDzaPepwvmW1xYwXZvJN7Pq87C
J3uBNlwm0l78Vo+bOT5IMNx4BZSnJ2YXJxidZnFfzfWx+U3MHfYot2pKwyc260kS
pouFeEhXX/tjby8O7IfGBmi1+OlEzRoQ0Eoy5pZPKt7NrOn4v0Vh2vOTEgMuExrh
FtjvTgh7TpWRt5s5aLFc5QVMUk+wSyA9KEaxvgCMeAuINy9rHYsHB5e9HljVUWGs
ed9f0rESNNTcOTuEen/eUWBb6MHtTYVWEXMWZLgd3eruVt2VhIz4cfGI/3/ThUo/
ZwIDAQAB
-----END PUBLIC KEY-----
";

    /**
     * 获取私钥
     * @return bool|resource
     */
    private static function getPrivateKey() {
        $privKey = self::$PRIVATE_KEY;
        return openssl_pkey_get_private($privKey);
    }

    /**
     * 获取公钥
     * @return bool|resource
     */
    private static function getPublicKey() {

        $publicKey = self::$PUBLIC_KEY;
        return openssl_pkey_get_public($publicKey);
    }

    /**
     * 创建签名
     * @param string $data 数据
     * @return null|string
     */
    public function createSign($data = '') {
        if (!is_string($data)) {
            return null;
        }
        return openssl_sign($data, $sign, self::getPrivateKey(), OPENSSL_ALGO_SHA256) ? base64_encode($sign) : null;
    }

    /**
     * 验证签名
     * @param string $data 数据
     * @param string $sign 签名
     * @return bool
     */
    public function verifySign($data = '', $sign = '') {
        if (!is_string($sign) || !is_string($sign)) {
            return false;
        }
        return (bool) openssl_verify($data, base64_decode($sign), self::getPublicKey(), OPENSSL_ALGO_SHA256);
    }

    /**
     * RSA私钥加密
     * @param string $private_key 私钥
     * @param string $data 要加密的字符串
     * @return string $encrypted 返回加密后的字符串
     * @author mosishu
     */
    public function privateEncrypt($data) {
        $encrypted = '';
        $pi_key = self::getPrivateKey();
        //最大允许加密长度为117，得分段加密
        $plainData = str_split($data, $this->ENCRYPT_BLOCK_SIZE); //生成密钥位数 1024 bit key
        foreach ($plainData as $chunk) {
            $partialEncrypted = '';
            $encryptionOk = openssl_private_encrypt($chunk, $partialEncrypted, $pi_key, OPENSSL_PKCS1_PADDING); //私钥加密
            if ($encryptionOk === false) {
                return false;
            }
            $encrypted .= $partialEncrypted;
        }

        return base64_encode($encrypted); //加密后的内容通常含有特殊字符，需要编码转换下，在网络间通过url传输时要注意base64编码是否是url安全的
    }

    /**
     * RSA公钥解密(私钥加密的内容通过公钥可以解密出来)
     * @param string $public_key 公钥
     * @param string $data 私钥加密后的字符串
     * @return string $decrypted 返回解密后的字符串
     * @author mosishu
     */
    public function publicDecrypt($data) {
        $decrypted = '';
        $pu_key = self::getPublicKey();
        $plainData = str_split(base64_decode($data), $this->DECRYPT_BLOCK_SIZE); //生成密钥位数 1024 bit key
        foreach ($plainData as $chunk) {
            $str = '';
            $decryptionOk = openssl_public_decrypt($chunk, $str, $pu_key, OPENSSL_PKCS1_PADDING); //公钥解密
            if ($decryptionOk === false) {
                return false;
            }
            $decrypted .= $str;
        }
        return $decrypted;
    }

    //RSA公钥加密
    public function publicEncrypt($data) {
        $encrypted = '';
        $pu_key = self::getPublicKey();
        $plainData = str_split($data, $this->ENCRYPT_BLOCK_SIZE);
        foreach ($plainData as $chunk) {
            $partialEncrypted = '';
            $encryptionOk = openssl_public_encrypt($chunk, $partialEncrypted, $pu_key, OPENSSL_PKCS1_PADDING); //公钥加密
            if ($encryptionOk === false) {
                return false;
            }
            $encrypted .= $partialEncrypted;
        }
        return base64_encode($encrypted);
    }

    //RSA私钥解密
    public function privateDecrypt($data) {
        $decrypted = '';
        $pi_key = self::getPrivateKey();
        $plainData = str_split(base64_decode($data), $this->DECRYPT_BLOCK_SIZE);
        foreach ($plainData as $chunk) {
            $str = '';
            $decryptionOk = openssl_private_decrypt($chunk, $str, $pi_key, OPENSSL_PKCS1_PADDING); //私钥解密
            if ($decryptionOk === false) {
                return false;
            }
            $decrypted .= $str;
        }
        return $decrypted;
    }

}
